/*******************************************************************************
 * Copyright (c) 2014 Joel Thurlby.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Joel Thurlby - initial API and implementation
 ******************************************************************************/
package jat.xtext.gantt.formatting

import org.eclipse.xtext.formatting.impl.AbstractDeclarativeFormatter
import org.eclipse.xtext.formatting.impl.FormattingConfig
import com.google.inject.Inject;
import jat.xtext.gantt.services.GanttTextGrammarAccess
import org.eclipse.xtext.Keyword
import org.eclipse.xtext.util.Pair;

/**
 * This class contains custom formatting description.
 * 
 * see : http://www.eclipse.org/Xtext/documentation.html#formatting
 * on how and when to use it 
 * 
 * Also see {@link org.eclipse.xtext.xtext.XtextFormattingTokenSerializer} as an example
 */
class GanttTextFormatter extends AbstractDeclarativeFormatter {

	@Inject extension GanttTextGrammarAccess

	override protected void configureFormatting(FormattingConfig c) {

		// COMMENTS
		c.setLinewrap(0, 1, 2).before(ML_COMMENTRule)
		c.setLinewrap(0, 1, 2).before(ML_COMMENTRule)
		c.setLinewrap(0, 1, 1).after(ML_COMMENTRule)

		// PROJECT : DESCRIPTION
		c.setLinewrap(2).before(projectAccess.descriptionAssignment_2)
		c.setIndentationIncrement.before(projectAccess.descriptionAssignment_2)
		c.setIndentationDecrement.after(projectAccess.descriptionAssignment_2)
		
		// PROJECT : FRAGMENTS
		c.setLinewrap(2).before(fragmentTeamRule)
		c.setLinewrap(2).before(fragmentRolesRule)
		c.setLinewrap(2).before(fragmentMilestonesRule)
		c.setLinewrap(2).before(fragmentWorkPackagesRule)

		// TEAM : PERSON
		c.setLinewrap(2).before(personRule)
		c.setIndentationIncrement.before(personRule)
		c.setIndentationDecrement.after(personRule)
		c.setLinewrap(1).before(genericAttributeRule)

		// ROLE
		c.setLinewrap.before(roleRule)
		c.setIndentationIncrement.before(roleRule)
		c.setIndentationDecrement.after(roleRule)

		// ROLE : TASK TYPE
		c.setLinewrap(2).before(taskTypeRule)
		c.setIndentationIncrement.before(taskTypeRule)
		c.setIndentationDecrement.after(taskTypeRule)
		c.setLinewrap.before(roleAccess.descriptionAssignment_4)
		c.setLinewrap.before(roleAccess.taskWeightKeyword_5)

		// MILESTONE
		c.setLinewrap(2).around(milestoneRule)
		c.setIndentationIncrement.before(milestoneRule)
		c.setIndentationDecrement.after(milestoneRule)
		c.setLinewrap.before(taskStateRule)

		// TASK
		c.setLinewrap.before(taskRule)
		c.setLinewrap.around(delayAnnotationRule)

		// TASK : DEPENDS-ON
		c.setLinewrap.before(taskAccess.dependsOnKeyword_4_0)
		c.setIndentationIncrement.before(taskAccess.dependsOnKeyword_4_0)
		c.setIndentationDecrement.after(taskAccess.taskDependenciesAssignment_4_1)

		// TASK : IMPLEMENTS
		c.setLinewrap.before(taskAccess.implementsKeyword_5_0)
		c.setIndentationIncrement.before(taskAccess.implementsKeyword_5_0)
		c.setIndentationDecrement.after(taskAccess.providedResourcesAssignment_5_1)

		// TASK : DURATION
		c.setLinewrap.around(taskDurationAccess.effortAssignment_4)
		c.setLinewrap.around(taskDurationAccess.completionAssignment_7)
		c.setLinewrap.around(taskDurationAccess.roleAssignmentsAssignment_8_4)

		// WORK PACKAGE
		c.setLinewrap(2).around(workPackageRule)
		c.setIndentationIncrement.before(workPackageRule)
		c.setIndentationDecrement.after(workPackageRule)

		// WORK PACKAGE : IS-PART-OF
		c.setLinewrap.before(workPackageAccess.isPartOfKeyword_2_0)
		c.setIndentationIncrement.before(workPackageAccess.isPartOfKeyword_2_0)
		c.setIndentationDecrement.after(workPackageAccess.packageParentAssignment_2_1)

		// WORK PACKAGE : DEPENDS-ON
		c.setLinewrap.before(workPackageAccess.dependsOnKeyword_3_0)
		c.setIndentationIncrement.before(workPackageAccess.dependsOnKeyword_3_0)
		c.setIndentationDecrement.after(workPackageAccess.packageDependenciesAssignment_3_1)

		// WORK PACKAGE : IMPLEMENTS
		c.setLinewrap.before(workPackageAccess.implementsKeyword_4_0)
		c.setIndentationIncrement.before(workPackageAccess.implementsKeyword_4_0)
		c.setIndentationDecrement.after(workPackageAccess.providedResourcesAssignment_4_1)

		// WORK PACKAGE : BODY
		c.setLinewrap.around(workPackageAccess.descriptionAssignment_6)
		c.setLinewrap.around(workPackageAccess.schedulingAssignment_7)
		c.setLinewrap.around(workPackageAccess.resourcesAssignment_8)
		c.setLinewrap.around(workPackageAccess.tasksAssignment_11_0)

		// WORK PACKAGE : RESOURCES
		c.setLinewrap.around(packageResourcesAccess.requiredResourcesAssignment_3)
		
		// WORK PACKAGE : SCHEDULING
		c.setLinewrap.around(schedulingAccess.earliestStartDateAssignment_3_2)
		c.setLinewrap.around(schedulingAccess.plannedStartDateAssignment_4_2)
		c.setLinewrap.around(schedulingAccess.dueDateAssignment_5_2)

		// BLOCK
		for (Pair<Keyword,Keyword> pair : grammar.findKeywordPairs("{", "}")) {
			c.setLinewrap(1).around(pair.first)
			c.setNoSpace.between(pair.first, pair.second)
			c.setIndentationIncrement.after(pair.first)
			c.setIndentationDecrement.before(pair.second)
			c.setLinewrap(1).around(pair.second)
		}

		// ARRAY
		for (Pair<Keyword,Keyword> pair : grammar.findKeywordPairs("[", "]")) {
			c.setLinewrap(1).around(pair.first)
			c.setIndentationIncrement.after(pair.first)
			c.setIndentationDecrement.before(pair.second)
			c.setLinewrap(1).around(pair.second)
		}

		// OPERATORS : NO SPACE BEFORE
		for (Keyword key : grammar.findKeywords(",")) {
			c.setNoSpace().before(key)
		}

		// OPERATORS : NO SPACE AFTER
		for (Keyword key : grammar.findKeywords("+")) {
			c.setNoSpace().after(key)
		}

		// OPERATORS : NO SPACE AROUND
		for (Keyword key : grammar.findKeywords("-")) {
			c.setNoSpace().around(key)
		}

		// OPERATORS : ONE SPACE AROUND
		for (Keyword key : grammar.findKeywords(":")) {
			c.setSpace(" ").around(key)
		}
	}
}
